﻿using Jurassic;
using System;
using System.Threading.Tasks;

namespace es.typescript
{
    /// <summary>
    /// js运行
    /// </summary>
    internal class JavaScriptExecutor
    {
        public ScriptEngine JSEngine { get; set; }

        public JavaScriptExecutor()
        {
            JSEngine = new ScriptEngine();
            JSEngine.EnableExposedClrTypes = true;  //启用外部对象
        }


        /// <summary>
        /// 注册对象
        /// </summary>
        /// <param name="name"></param>
        /// <param name="obj"></param>
        public void SetObject(string name, object obj)
        {
            JSEngine.SetGlobalValue(name, obj);
        }

        /// <summary>
        /// 注册函数
        /// </summary>
        /// <param name="name"></param>
        /// <param name="fun"></param>
        public void SetFunction(string name, Action fun)
        {
            JSEngine.SetGlobalFunction(name, fun);
        }

        /// <summary>
        /// 获取对象
        /// </summary>
        /// <param name="name"></param>
        /// <returns></returns>
        public object GetObject(string name)
        {
            return JSEngine.GetGlobalValue(name);
        }

        /// <summary>
        /// 获取对象
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="name"></param>
        /// <returns></returns>
        public T GetObject<T>(string name)
        {
            return JSEngine.GetGlobalValue<T>(name);
        }


        /// <summary>
        /// 调用脚本函数
        /// </summary>
        /// <param name="func"></param>
        /// <param name="args"></param>
        /// <returns></returns>
        public object CallFunc(string func, params object[] args)
        {
            return JSEngine.CallGlobalFunction(func, args);
        }


        /// <summary>
        /// 调用脚本函数
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="func"></param>
        /// <param name="args"></param>
        /// <returns></returns>
        public T CallFunc<T>(string func, params object[] args)
        {
            return JSEngine.CallGlobalFunction<T>(func, args);
        }


        /// <summary>
        ///// 允许使用console对象
        /// </summary>
        public void EnableConsoleApi()
        {
            JSEngine.SetGlobalValue("console", new Jurassic.Library.FirebugConsole(JSEngine));
        }

        public T Evaluate<T>(string expression)
        {
            return JSEngine.Evaluate<T>(expression);
        }

        public async Task<T> EvaluteAsync<T>(string expression)
        {
            return await Task.Run(() => EvaluteAsync<T>(expression));
        }


        /// <summary>
        /// 将js编译为可执行代码
        /// </summary>
        /// <param name="js"></param>
        /// <returns></returns>
        public CompiledScript Compile(string js)
        {
            return JSEngine.Compile(new StringScriptSource(js));
        }


        /// <summary>
        /// 将js编译为可以执行代码
        /// </summary>
        /// <param name="js"></param>
        /// <returns></returns>
        public async Task<CompiledScript> CompileAsync(string js)
            => await Task.Run(() => Compile(js));



        public void Execute(string js)
        {
            JSEngine.Execute(js);
        }

        public void Execute(CompiledScript script)
        {
            script.Execute();
        }


        public async Task ExecuteAsync(string js)
        {
            await Task.Run(() => Execute(js));
        }


        public async Task ExecuteAsync(CompiledScript script)
        {
            await Task.Run(() => Execute(script));
        }
    }
}